<?php

require_once 'standard/re/Scalar.php';
require_once 'standard/re/List.php';

require_once 'standard-re/Type/Test_Types/scalar.Rational.php';

class re_Test_Point extends re_Scalar
{

	public function _declarePossRep(){
		
		return array(
		
			'cartesian'=>array(
				'x'=>'re_Test_Rational',
				'y'=>'re_Test_Rational'
			),
			
			'polar'=>array(
				'r'=>'re_Test_Rational',
				'theta'=>'re_Test_Rational'
			)
		);
	}
	
	protected function _cartesian(re_Test_Rational $x, re_Test_Rational $y){
		
		$this->_setThe("x", $x);

		$this->_setThe("y", $y);
			
	}
	
	protected function _polar(re_Test_Rational $r, re_Test_Rational $theta){
	
		$this->_selectorCartesian(
			$r->times($theta->cos()),
			$r->times($theta->sin())
		);
	}
	
	public function theX(){
		return $this->_getThe("x");
	}
	
	public function theY(){
	
		return $this->_getThe("y");
	}
	
	
	public function theR(){
	
		return $this->theX()->raise(2)
					->plus($this->theY()->raise(2))
					->sqrRt();
	}
	
	public function theTheta(){
		return $this->theY()->divide($this->theX())->arcTan();
	}
	
	//implementation related operators
	//standard selector
	static public function _ss($rep){
		
		$rep = (object)re_List::value((array)json_decode($rep))->rep();
		
		return re::select(
			__CLASS__
		  ,array(
				//necessary to cast the components, because sometimes, driver storage messes
				//the original type.
				'x'=>re::select('re_Test_Rational', (double)$rep->X, 'decimal')
			   ,'y'=>re::select('re_Test_Rational', (double)$rep->Y, 'decimal')
		   )
		  ,'cartesian'
		);
	}
	
	//standard representation
	public function _sr( $recurse = FALSE ){
	
		return re_List::value(array(
			'x'=>$this->theX()->_sr()
		   ,'y'=>$this->theY()->_sr()
		))->rep();
	}
	
	//standard storage representation
	public function _ssr(){
		
		return json_encode($this->_sr());
	}
}